/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2021 Marcus Britanicus (https://gitlab.com/marcusbritanicus)
 * Copyright (c) 2021 Abrar (https://gitlab.com/s96Abrar)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 **/


#include "wayfire-shell-unstable-v2-client-protocol.h"

#include "wayqt/WayfireShell.hpp"

WQt::Shell::Shell( zwf_shell_manager_v2 *shellMgr ) {
    mObj = shellMgr;
}


WQt::Shell::~Shell() {
    zwf_shell_manager_v2_destroy( mObj );
}


WQt::WfOutput *WQt::Shell::getOutput( wl_output *wlOut ) {
    /**
     * We get the wfOut object. Now we need to send this to Output*
     * and hook it up to a listener.
     */
    zwf_output_v2 *wfOut = zwf_shell_manager_v2_get_wf_output( mObj, wlOut );

    return new WQt::WfOutput( wfOut );
}


WQt::Surface *WQt::Shell::getSurface( wl_surface *wlSurf ) {
    zwf_surface_v2 *wfSurf = zwf_shell_manager_v2_get_wf_surface( mObj, wlSurf );

    return new WQt::Surface( wfSurf );
}


zwf_shell_manager_v2 *WQt::Shell::get() {
    return mObj;
}


/**
 * Output Wrapper
 */

WQt::WfOutput::WfOutput( zwf_output_v2 *wfOut ) {
    mObj = wfOut;
}


WQt::WfOutput::~WfOutput() {
    zwf_output_v2_destroy( mObj );
}


void WQt::WfOutput::setup() {
    zwf_output_v2_add_listener( mObj, &mWfOutputListener, this );
}


WQt::HotSpot *WQt::WfOutput::createHotSpot( HotSpotPoint hsPos, uint32_t threshold, uint32_t timeout ) {
    zwf_hotspot_v2 *wfHS = zwf_output_v2_create_hotspot( mObj, hsPos, threshold, timeout );

    return new WQt::HotSpot( wfHS );
}


zwf_output_v2 *WQt::WfOutput::get() {
    return mObj;
}


void WQt::WfOutput::handleEnterFullScreen( void *data, zwf_output_v2 *wfOutput ) {
    Q_UNUSED( wfOutput );

    WfOutput *wfOpWrap = reinterpret_cast<WfOutput *>(data);
    emit wfOpWrap->enteredFullScreen();
}


void WQt::WfOutput::handleLeaveFullScreen( void *data, zwf_output_v2 *wfOutput ) {
    Q_UNUSED( wfOutput );

    WfOutput *wfOpWrap = reinterpret_cast<WfOutput *>(data);
    emit wfOpWrap->leftFullScreen();
}


const struct zwf_output_v2_listener WQt::WfOutput::mWfOutputListener = {
    handleEnterFullScreen,
    handleLeaveFullScreen,
};

/**
 * HotSpot Wrapper
 */

WQt::HotSpot::HotSpot( zwf_hotspot_v2 *wfHS ) {
    mObj = wfHS;
}


WQt::HotSpot::~HotSpot() {
    zwf_hotspot_v2_destroy( mObj );
}


void WQt::HotSpot::setup() {
    zwf_hotspot_v2_add_listener( mObj, &mWfHotSpotListener, this );
}


zwf_hotspot_v2 *WQt::HotSpot::get() {
    return mObj;
}


void WQt::HotSpot::handleEnterHotSpot( void *data, zwf_hotspot_v2 *wfHotspot ) {
    Q_UNUSED( wfHotspot );

    HotSpot *wfHsWrap = reinterpret_cast<HotSpot *>(data);
    emit wfHsWrap->enteredHotSpot();
}


void WQt::HotSpot::handleLeaveHotSpot( void *data, zwf_hotspot_v2 *wfHotspot ) {
    Q_UNUSED( wfHotspot );

    HotSpot *wfHsWrap = reinterpret_cast<HotSpot *>(data);
    emit wfHsWrap->leftHotSpot();
}


const struct zwf_hotspot_v2_listener WQt::HotSpot::mWfHotSpotListener = {
    handleEnterHotSpot,
    handleLeaveHotSpot,
};

/**
 * Surface Wrapper
 */

WQt::Surface::Surface( zwf_surface_v2 *wf_surf ) {
    mObj = wf_surf;
}


WQt::Surface::~Surface() {
    zwf_surface_v2_destroy( mObj );
}


void WQt::Surface::move() {
    zwf_surface_v2_interactive_move( mObj );
}


zwf_surface_v2 *WQt::Surface::get() {
    return mObj;
}
